//GPU 动画（无光照）
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it uses non-square matrices
#pragma exclude_renderers gles
#ifndef GPU_ANIMATION_LIB_INCLUDED
#define GPU_ANIMATION_LIB_INCLUDED

float3 doTransformPoint(float4x4 transform, float3 pt)
{
    return mul(transform, float4(pt.x, pt.y, pt.z, 1)).xyz;
}

float3 doTransformVector(float3x3 transform, float3 vec)
{
    return mul(transform, vec);
}

float4 loadBoneMatrixTexture(sampler2D animatedBoneMatrices, float2 size, int frameIndex, int boneIndex, int i)
{
    //float2 uv = float2((boneIndex * 3) + i, frameIndex) / size; //此处贴图需设置为point
    float2 uv = float2((boneIndex * 3) + i + 0.5, frameIndex + 0.5) / size; //此处贴图可设置为双线性插值
    return tex2Dlod(animatedBoneMatrices, float4(uv, 0, 0)); //(x,y)
}

void calculateFrameValues_Unlit(float3 position,
                          sampler2D animatedBoneMatrices, float2 size,
                          float2 boneWeights[4], int frameIndex,
                          out float3 positionOut)
{
    positionOut = float3(0, 0, 0);
    //每个顶点最多受4个骨骼影响
    for (int i = 0; i < 4; i++)
    {
        float boneWeight = boneWeights[i].y; //第二通道存储权重值（MeshBaker中生成）
        if (boneWeight != 0)
        {
            float boneIndex = boneWeights[i].x; //第一通道存储骨骼索引值（MeshBaker中生成）

            //读取骨骼变换矩阵：
            float4 m0 = loadBoneMatrixTexture(animatedBoneMatrices, size, frameIndex, boneIndex, 0); //第一列
            float4 m1 = loadBoneMatrixTexture(animatedBoneMatrices, size, frameIndex, boneIndex, 1); //第二列
            float4 m2 = loadBoneMatrixTexture(animatedBoneMatrices, size, frameIndex, boneIndex, 2); //第三列
            float4 m3 = float4(0, 0, 0, 1); //齐次（点）

            float4x4 animatedBoneMatrix = float4x4(m0, m1, m2, m3); //还原变换矩阵
            positionOut += boneWeight * doTransformPoint(animatedBoneMatrix, position); //位移变换
        }
    }
}

void calculateFrameValues_Lit(float3 position, float3 normal,
                          sampler2D animatedBoneMatrices, float2 size,
                          float2 boneWeights[4], int frameIndex,
                          out float3 positionOut, out float3 normalOut)
{
    positionOut = float3(0, 0, 0);
    normalOut = float3(0, 0, 0);
    //每个顶点最多受4个骨骼影响
    for (int i = 0; i < 4; i++)
    {
        float boneWeight = boneWeights[i].y; //第二通道存储权重值（MeshBaker中生成）
        if (boneWeight != 0)
        {
            float boneIndex = boneWeights[i].x; //第一通道存储骨骼索引值（MeshBaker中生成）

            //读取骨骼变换矩阵：
            float4 m0 = loadBoneMatrixTexture(animatedBoneMatrices, size, frameIndex, boneIndex, 0); //第一列
            float4 m1 = loadBoneMatrixTexture(animatedBoneMatrices, size, frameIndex, boneIndex, 1); //第二列
            float4 m2 = loadBoneMatrixTexture(animatedBoneMatrices, size, frameIndex, boneIndex, 2); //第三列
            float4 m3 = float4(0, 0, 0, 1); //齐次（点）

            float4x4 animatedBoneMatrix = float4x4(m0, m1, m2, m3); //还原变换矩阵
            positionOut += boneWeight * doTransformPoint(animatedBoneMatrix, position); //位移变换
            normalOut += boneWeight * doTransformVector(animatedBoneMatrix, normal);
        }
    }
}

void AnimateBlendUnlit(float3 position,
                        float2x4 uvs, sampler2D animatedBoneMatrices, float2 size, float2x3 animationState,
                        out float3 positionOut)
{
    positionOut = float3(0, 0, 0);
    float2 boneWeights[4] = {
        float2(uvs._m00, uvs._m01), float2(uvs._m02, uvs._m03),
        float2(uvs._m10, uvs._m11), float2(uvs._m12, uvs._m13)
    };

    //动画混合
    for (int blendIndex = 0; blendIndex < 2; blendIndex++)
    {
        float blendFactor = animationState[blendIndex][0]; //混合因子
        if (blendFactor > 0)
        {
            float transitionNextFrame = animationState[blendIndex][1];
            float prevFrameFrac = 1.0 - transitionNextFrame;
            float frameIndex = animationState[blendIndex][2];
            float3 posOutBefore, posOutAfter;
            calculateFrameValues_Unlit(position, animatedBoneMatrices, size, boneWeights, frameIndex,
                                 posOutBefore);
            calculateFrameValues_Unlit(position, animatedBoneMatrices, size, boneWeights, frameIndex + 1,
                                 posOutAfter);
            //两帧之间插值
            positionOut += blendFactor * (prevFrameFrac * posOutBefore + transitionNextFrame * posOutAfter);
        }
    }
}

void AnimateBlendLit(float3 position, float3 normal,
                        float2x4 uvs, sampler2D animatedBoneMatrices, float2 size, float2x3 animationState,
                        out float3 positionOut, out float3 normalOut)
{
    positionOut = float3(0, 0, 0);
    normalOut = float3(0, 0, 0);
    float2 boneWeights[4] = {
        float2(uvs._m00, uvs._m01), float2(uvs._m02, uvs._m03),
        float2(uvs._m10, uvs._m11), float2(uvs._m12, uvs._m13)
    };

    //动画混合
    for (int blendIndex = 0; blendIndex < 2; blendIndex++)
    {
        float blendFactor = animationState[blendIndex][0]; //混合因子
        if (blendFactor > 0)
        {
            float transitionNextFrame = animationState[blendIndex][1];
            float prevFrameFrac = 1.0 - transitionNextFrame;
            float frameIndex = animationState[blendIndex][2];
            float3 posOutBefore, posOutAfter;
            float3 normalOutBefore, normalOutAfter;
            calculateFrameValues_Lit(position, normal, animatedBoneMatrices, size, boneWeights, frameIndex,
                                 posOutBefore, normalOutBefore);
            calculateFrameValues_Lit(position, normal, animatedBoneMatrices, size, boneWeights, frameIndex + 1,
                                 posOutAfter, normalOutAfter);
            //两帧之间插值
            positionOut += blendFactor * (prevFrameFrac * posOutBefore + transitionNextFrame * posOutAfter);
            normalOut += blendFactor * (prevFrameFrac * normalOutBefore + transitionNextFrame * normalOutAfter);
        }
    }
}

#endif